package com.basker.pisces.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import com.basker.pisces.exception.ExceptionFactory;

/**
 * 属性文件工具类
 *
 * @author hangwen
 */
public class PropertiesFileUtils {

    /**
     * 读取文件生成Properties，或文件不存在返回一个空的Properties
     *
     * @param file
     * @return
     */
    public static Properties load(File file) {
        return load(file, false);
    }

    /**
     * 读取文件生成Properties，或文件不存在返回一个空的Properties
     *
     * @param file
     * @param ordered 是否有序加载文件中的属性
     * @return
     */
    public static Properties load(File file, boolean ordered) {
        try {
            FileInputStream fis = new FileInputStream(file);
            return load(fis, ordered);
        } catch (FileNotFoundException e) {
            return new Properties();
        }
    }

    /**
     * 读取流生成Properties
     *
     * @param inputStream
     * @return
     */
    public static Properties load(InputStream inputStream) {
        return load(inputStream, false);
    }

    /**
     * 读取流生成Properties,可以指定是否有序加载到Properties对象中
     *
     * @param inputStream
     * @param ordered     是否有序加载文件中的属性
     * @return
     */
    public static Properties load(InputStream inputStream, boolean ordered) {
        Properties p = ordered ? new OrderedProperties() : new Properties();
        return load(p, inputStream);
    }

    /**
     * 读取多个properties文件的路径
     *
     * @param propertiesPaths
     * @return
     */
    public static Properties load(String... propertiesPaths) {
        Properties props = new Properties();

        for (String propertiesPath : propertiesPaths) {
            if (!propertiesPath.startsWith("/")) {
                propertiesPath = "/" + propertiesPath;
            }

            InputStream inputStream = PropertiesFileUtils.class.getResourceAsStream(propertiesPath);
            props = load(props, inputStream);
        }

        return props;

    }

    /**
     * 将properties保存到指定文件
     *
     * @param properties
     * @param filePath
     */
    public static void savePropertiesFile(Properties properties, File file) {
        FileOutputStream out = null;

        try {
            out = new FileOutputStream(file);
            properties.store(out, null);
        } catch (IOException e) {
            throw ExceptionFactory.createRuntimeException(e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {

                }
            }
        }

    }

    /**
     * 将properties保存到指定文件
     *
     * @param properties
     * @param filePath
     */
    public static void savePropertiesFile(Properties properties, String filePath) {
        savePropertiesFile(properties, new File(filePath));
    }

    /**
     * 更新属性文件
     *
     * @param filePath
     * @param properties
     */
    public static void updatePropertiesFile(String filePath, Map<String, String> properties) {
        Properties pro = new Properties();

        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream(filePath);
            pro.load(in);

            for (Entry<String, String> propValue : properties.entrySet()) {
                if (propValue == null || propValue.getValue() == null) {
                    continue;
                }
                pro.setProperty(propValue.getKey(), propValue.getValue());
            }

            // 重新写入配置文件
            out = new FileOutputStream(filePath);
            pro.store(out, null);
        } catch (IOException e) {
            throw ExceptionFactory.createRuntimeException(e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }

                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {

            }
        }
    }

    /**
     * 读取流,填充指定的Properties
     *
     * @param props
     * @param inputStream
     * @return
     */
    private static Properties load(Properties props, InputStream inputStream) {
        try {
            if (inputStream != null) {
                props.load(new InputStreamReader(inputStream, "UTF-8"));
            }

            return props;
        } catch (IOException e) {
            throw ExceptionFactory.createRuntimeException(e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {

                }
            }
        }
    }

}

class OrderedProperties extends Properties {

    private static final long serialVersionUID = -4627607243846121965L;

    private final LinkedHashSet<Object> keys = new LinkedHashSet<Object>();

    @Override
    public Enumeration<Object> keys() {
        return Collections.<Object>enumeration(keys);
    }

    @Override
    public Set<Object> keySet() {
        return keys;
    }

    @Override
    public Object put(Object key, Object value) {
        keys.add(key);
        return super.put(key, value);
    }

    @Override
    public Set<String> stringPropertyNames() {
        Set<String> set = new LinkedHashSet<String>(this.keys.size(), 1);

        for (Object key : this.keys) {
            set.add((String) key);

        }

        return set;

    }
}
